#include "sentenciasql.h"

SentenciaSql::SentenciaSql()
{
    m_eComando = Nulo;
}
SentenciaSql::SentenciaSql(QString strSql)
{
    m_eComando = Nulo;
    setSql(strSql);
}

SentenciaSql::~SentenciaSql()
{
}

void SentenciaSql::agregarFrom(const QString &str)
{
    if (m_strFrom.indexOf(str) == -1)
    {
        enlazarStrings(m_strFrom, ",\n\t", str);
    }
}

void SentenciaSql::agregarLeftJoin(const QString& strTabla, const QString& strOn)
{
    agregarJoin(strTabla, "LEFT", strOn);
}

void SentenciaSql::agregarRightJoin(const QString& strTabla, const QString& strOn)
{
    agregarJoin(strTabla, "RIGHT", strOn);
}

void SentenciaSql::agregarInnerJoin(const QString& strTabla, const QString& strOn)
{
    agregarJoin(strTabla, "INNER", strOn);
}

void SentenciaSql::agregarJoin(const QString& strTabla, const QString& strDireccion, const QString& strOn)
{
    if (m_strFrom.isEmpty())
        return;

    m_strFrom = "(" + m_strFrom + ") " + strDireccion + " JOIN " + strTabla + " ON " + strOn;
}


void SentenciaSql::setSql(QString strSql)
{
    m_strSelect.clear();
    m_strFrom.clear();
    m_strWhere.clear();
    m_strGroup.clear();
    m_strHaving.clear();
    m_strOrder.clear();

    m_eComando = Nulo;
    m_strTabla.clear();
    m_strListaCampos.clear();
    m_strListaValores.clear();
    m_strListaModificaciones.clear();

    QString strSqlMayusculas = strSql.toUpper();

    int selectPos = strSqlMayusculas.indexOf("SELECT");

    if (selectPos < 0) {
        return;
    }

    int fromPos = strSqlMayusculas.indexOf("FROM");
    int wherePos = strSqlMayusculas.indexOf("WHERE");
    int groupPos = strSqlMayusculas.indexOf("GROUP BY");
    int havingPos = strSqlMayusculas.indexOf("HAVING");
    int orderPos = strSqlMayusculas.indexOf("ORDER BY");

    if (orderPos != -1)
    {
        m_strOrder = strSql.right(strSql.length() - orderPos - 8);
        m_strOrder = m_strOrder.trimmed();
        strSql = strSql.left(orderPos);
    }
    else {
        m_strOrder.clear();
    }

    if (havingPos != -1)
    {
        m_strHaving = strSql.right(strSql.length() - havingPos - 6);
        m_strHaving = m_strHaving.trimmed();
        strSql = strSql.left(havingPos);
    }
    else
        m_strHaving.clear();


    if (groupPos != -1)
    {
        m_strGroup = strSql.right(strSql.length() - groupPos - 8);
        m_strGroup = m_strGroup.trimmed();
        strSql = strSql.left(groupPos);
    }
    else
        m_strGroup.clear();

    if (wherePos != -1)
    {
        m_strWhere = strSql.right(strSql.length() - wherePos - 5);
        m_strWhere = m_strWhere.trimmed();
        strSql = strSql.left(wherePos);
    }
    else
        m_strWhere.clear();

    if (fromPos != -1)
    {
        m_strFrom = strSql.right(strSql.length() - fromPos - 4);
        m_strFrom = m_strFrom.trimmed();
        strSql = strSql.left(fromPos);
    }
    else
        m_strFrom.clear();

    if (selectPos != -1)
    {
        m_eComando = Select;
        m_strSelect = strSql.right(strSql.length() - selectPos - 6);
        m_strSelect = m_strSelect.trimmed();
    }
    else
        m_strSelect.clear();
}

QString SentenciaSql::getSql() const
{
    switch (m_eComando)
    {
    case Select:
        return getSelectSql();
        break;
    case Insert:
        return getInsertSql();
        break;
    case Update:
        return getUpdateSql();
        break;
    case Delete:
        return getDeleteSql();
        break;
    default:
        return "";
    }
}

QString SentenciaSql::getSelectSql() const
{
    QString strSql;

    if (!m_strSelect.isEmpty())
        strSql += "SELECT " + m_strSelect;

    if (!m_strFrom.isEmpty())
        strSql += "\nFROM " + m_strFrom;

    if (!m_strWhere.isEmpty())
        strSql += "\nWHERE " + m_strWhere;

    if (!m_strGroup.isEmpty())
        strSql += "\nGROUP BY " + m_strGroup;

    if (!m_strHaving.isEmpty())
        strSql += "\nHAVING " + m_strHaving;

    if (!m_strOrder.isEmpty())
        strSql += "\nORDER BY " + m_strOrder;

    return strSql;
}

QString SentenciaSql::getInsertSql() const
{
    QString strSql;

    strSql = "INSERT INTO " + m_strTabla +
            "(" + m_strListaCampos + ")\nVALUES(" + m_strListaValores + ")";

    return strSql;
}

QString SentenciaSql::getUpdateSql() const
{
    QString strSql;

    strSql = "UPDATE " + m_strTabla +
        " SET " + m_strListaModificaciones;
    if (!m_strWhere.isEmpty())
        strSql += "\nWHERE " + m_strWhere;

    return strSql;
}

QString SentenciaSql::getDeleteSql() const 
{
    QString strSql;

    if (!m_strWhere.isEmpty())
        strSql = "DELETE FROM " + m_strTabla + " WHERE " + m_strWhere;
    else
        strSql = "DELETE FROM " + m_strTabla;

    return strSql;
}

void SentenciaSql::asignar(QString strCampo, QString strValor)
{
    // Se sustituyen las comillas por dos comillas
    strValor.replace("'", "''");

    if (strValor.isEmpty())
        asignarValorSql(strCampo, "Null");
    else
        asignarValorSql(strCampo, "'" + strValor + "'");
}

void SentenciaSql::asignar(QString strCampo, double dblValor)
{
    asignarValorSql(strCampo, QString::number(dblValor));
}

void SentenciaSql::asignar(QString strCampo, QDateTime dtValor)
{
    if (dtValor.isValid()) {
        QString strFecha = dtValor.toString("dd/MM/yyyy hh:mm:ss");
        asignarValorSql(strCampo, "to_date('" + strFecha + "', 'dd/mm/yyyy hh24:mi:ss')");
    } else {
        asignarValorSql(strCampo, "Null");
    }
}

void SentenciaSql::asignar(QString strCampo, QDate dtValor)
{
    if (dtValor.isValid()) {
        QString strFecha = dtValor.toString("dd/MM/yyyy");
        asignarValorSql(strCampo, "to_date('" + strFecha + "', 'dd/mm/yyyy')");
    } else {
        asignarValorSql(strCampo, "Null");
    }
}

void SentenciaSql::asignar(QString strCampo, bool bValor)
{
    asignarValorSql(strCampo, bValor ? "1" : "0");
}

void SentenciaSql::asignar(QString strCampo, qint64 nValor)
{
    asignarValorSql(strCampo, QString::number(nValor));
}

void SentenciaSql::asignar(QString strCampo, quint64 nValor)
{
    asignarValorSql(strCampo, QString::number(nValor));
}

void SentenciaSql::asignarNull (QString strCampo)
{
    asignarValorSql(strCampo, "Null");
}

void SentenciaSql::limpiarValores()
{
    m_strListaCampos.clear();
    m_strListaValores.clear();
    m_strListaModificaciones.clear();
    m_strFind.clear();
}

void SentenciaSql::asignarValorSql(QString strCampo, QString strValorSql)
{
    if (strCampo.isEmpty()) {
        return;
    }

    if (strValorSql.isEmpty()) {
        strValorSql = "Null";
    }

    strValorSql = strValorSql.trimmed();
    strCampo = strCampo.trimmed();
//    if (strCampo.indexOf('[') == -1)
//        strCampo = EncorchetarSql(strCampo);

    if (strValorSql.compare("null", Qt::CaseInsensitive) != 0) {
        enlazarStrings(m_strFind, " AND ", strCampo + " = " + strValorSql);
    }

    int nPunto = strCampo.indexOf('.');
    if (nPunto != -1)
        strCampo = strCampo.right(strCampo.length() - nPunto - 1);

    if (m_eComando == Insert)
    {
        if (!m_strListaCampos.isEmpty())
            m_strListaCampos += ", ";
        m_strListaCampos += strCampo;
        if (!m_strListaValores.isEmpty())
            m_strListaValores += ", ";
        m_strListaValores += strValorSql;
    }
    else if (m_eComando == Update)
    {
        if (!m_strListaModificaciones.isEmpty())
            m_strListaModificaciones += ", ";
        m_strListaModificaciones += strCampo + " = " + strValorSql;
    }
}

void SentenciaSql::enlazarStrings(QString& strExistente, QString strSeparador, QString strNuevo)
{
    if (strNuevo.isEmpty())
        return;

    if (!strExistente.isEmpty())
        strExistente += strSeparador;

    strExistente += strNuevo;
}

void SentenciaSql::enlazarStringsExpr(QString& strExistente, QString strSeparador, QString strNuevo)
{
    if (strNuevo.isEmpty())
        return;

    if (strExistente.isEmpty())
        strExistente = strNuevo;
    else
        strExistente = "(" + strExistente + ")" + strSeparador + "(" + strNuevo + ")";
}
